﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Runtime.InteropServices;
using WFNetLib.PacketProc;

namespace WFNetLib.TCP
{
    /// <summary>
    /// 保存数据的回调函数
    /// </summary>
    /// <param name="s1"></param>
    /// <param name="s2"></param>
    /// <returns></returns>
    public delegate object SaveDataProcessCallbackDelegate(ref byte[] tempbuffer, ref byte[] buffer, ref int dataOffset, int length);
    
    public class TCPAsyncServer 
    {
        public static int bufferSize = 2048;
        public string TCPServerName = "";
        public int TCPServerPort = 8001;
        private Socket listener = null;
        //private ManualResetEvent AcceptDone = new ManualResetEvent(false);
        //private ManualResetEvent sendDone = new ManualResetEvent(false);
        private Mutex ClientListMutex = new Mutex();
        private Hashtable ClientList = new Hashtable();
        public IAsyncResult AcceptIAsyncResult;
        public Exception LastException;
        //回调函数
        public SaveDataProcessCallbackDelegate SaveDataProcessCallback=null;

        public IAsyncResult GetClientSendIAsyncResult(string clientkey)
        {
            try
            {
                ClientListMutex.WaitOne();
                ClientContext client = (ClientContext)ClientList[clientkey];
                if (client != null)
                {
                    return client.SendIAsyncResult;
                }
                else
                    throw (new Exception("指定的客户端没有找到!"));
            }
            catch (System.Exception ex)
            {
                LastException = ex;
            }
            finally
            {
                try
                {
                    ClientListMutex.ReleaseMutex();
                }
                catch
                {

                }
            }
            return null;
        }
        public IAsyncResult GetClientReceiveIAsyncResult(string clientkey)
        {
            try
            {
                ClientListMutex.WaitOne();
                ClientContext client = (ClientContext)ClientList[clientkey];
                if (client != null)
                {
                    return client.ReceiveIAsyncResult;
                }
                else
                    throw (new Exception("指定的客户端没有找到!"));
            }
            catch (System.Exception ex)
            {
                LastException = ex;
            }
            finally
            {
                try
                {
                    ClientListMutex.ReleaseMutex();
                }
                catch
                {

                }
            }
            return null;
        }
        ///
        /// 停止服务器
        ///
        public void Stop()
        {
            if (listener == null)
                return;
            listener.Close();
            ClientListMutex.WaitOne();
            foreach (DictionaryEntry c in ClientList)
            {
                ClientContext client = (ClientContext)c.Value;
                client.ClientSocket.Shutdown(SocketShutdown.Both);
                client.ClientSocket.Close();
            }
            ClientList.Clear();
            ClientListMutex.ReleaseMutex();
            //listener = null;
        }
        ///
        /// 开始监听访问
        ///
        public void Start()
        {
            try
            {
                if (SaveDataProcessCallback == null)
                    throw (new Exception("没有定义数据的处理回调!"));
                if (listener != null)
                {
                    //listener.Dispose();
                    listener = null;
                }
                listener = new Socket(AddressFamily.InterNetwork,
                 SocketType.Stream, ProtocolType.Tcp);
//                 if (TCPServerName.Trim() == "")
//                 {
//                     //ServerName = IPAddress.Any;
//                     IPHostEntry ipHostEntry = Dns.GetHostEntry(Dns.GetHostName());
//                     foreach (IPAddress ip in ipHostEntry.AddressList)
//                     {
//                         if (ip.IsIPv6LinkLocal)
//                             continue;
//                         if (ipHostEntry.AddressList.Length != 0)
//                         {
//                             TCPServerName = ip.ToString();
//                             break;
//                         }
//                     }
//                 }
                IPEndPoint localEndPoint;
                if (TCPServerName.Trim() == "")
                {
                    localEndPoint = new IPEndPoint(IPAddress.Any, TCPServerPort);
                }
                else
                    localEndPoint = new IPEndPoint(IPAddress.Parse(TCPServerName), TCPServerPort);
                listener.Bind(localEndPoint);
                listener.Listen(10);
                AcceptIAsyncResult=listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
            }
            catch (Exception e)
            {
                OnErrorServerEvent(new ErrorServerEventArgs(e, null,TCPErrorType.Unkown));
                LastException = e;
            }
        }
        private void AcceptCallback(IAsyncResult ar)
        {
            Socket handler = null;
            try
            {
                Socket listener = (Socket)ar.AsyncState;
                handler = listener.EndAccept(ar);
                ClientContext client = new ClientContext(handler);
                OnAcceptServerEvent(new AcceptServerEventArgs(client));
                ClientListMutex.WaitOne();
                ClientList.Add(client.key, client);
                client.ReceiveIAsyncResult=client.netStream.BeginRead(client.tempbuffer, 0, ClientContext.BUFFER_SIZE, new AsyncCallback(AsyncCallbackReadFromNetStream), client);
                AcceptIAsyncResult=listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                client = null;
            }
            catch (ObjectDisposedException)//服务已经关闭
            {

            }
            catch (Exception e)
            {
                OnErrorServerEvent(new ErrorServerEventArgs(e, null, TCPErrorType.Unkown));
                LastException = e;
            }
            finally
            {
                //AcceptDone.Set();
                try
                {
                    ClientListMutex.ReleaseMutex();
                }
                catch
                {

                }
            }
        }
        /// <summary>
        /// 从网络流异步读取数据回调函数
        /// </summary>
        /// <param name="result"></param>
        private void AsyncCallbackReadFromNetStream(IAsyncResult result)
        {
            try
            {
                ClientContext Client = (ClientContext)result.AsyncState;
                int readLen = Client.netStream.EndRead(result);                
                if (readLen == 0)
                {
                    if (Client.ClientSocket.Poll(-1, SelectMode.SelectRead))
                    {
                        OnDisconnectServerEvent(new DisconnectEventArgs((ClientContext)result.AsyncState));
                    }
                }
                else
                {
                    Client.UpdateTime = DateTime.Now;
                    object o = SaveDataProcessCallback(ref Client.tempbuffer, ref Client.netDataBuffer, ref Client.netDataOffset, readLen);
                    if (o != null)
                        OnReceiveServerEvent(new ReceiveServerEventArgs(o, Client));
                    Client.ReceiveIAsyncResult=Client.netStream.BeginRead(Client.tempbuffer, 0, ClientContext.BUFFER_SIZE, new AsyncCallback(AsyncCallbackReadFromNetStream), Client);
                }
            }
            catch(IOException e)
            {
                if (e.InnerException.GetType() == typeof(SocketException))
                {
                    SocketException ex=(SocketException)e.InnerException;
                    ClientContext Client = (ClientContext)result.AsyncState;
                    switch (ex.ErrorCode)
                    {
                        case 10054://客户端断开连接
                            ClientListMutex.WaitOne();
                            ClientList.Remove(Client.key);
                            ClientListMutex.ReleaseMutex();
                            OnDisconnectServerEvent(new DisconnectEventArgs((ClientContext)result.AsyncState));
                            break;
                        default:
                            OnErrorServerEvent(new ErrorServerEventArgs(e, TCPErrorType.Unkown));                            
                            break;
                    }
                }
                LastException = e;
            }
            catch (SystemException e)
            {
                OnErrorServerEvent(new ErrorServerEventArgs(e, TCPErrorType.Unkown));
                LastException = e;
            }
        }
        ///
        /// 发送一个流数据
        ///
        public void Send(string clientkey, MemoryStream mStream)
        {
            Send(clientkey, mStream.GetBuffer());
        }  
        ///
        /// 发送一个流数据
        ///
        public void Send(string clientkey, byte[] txBytes)
        {
            ClientContext client = null;
            try
            {
                ClientListMutex.WaitOne();
                client = (ClientContext)ClientList[clientkey];
                if (client != null)
                {                   
                    Send(client, txBytes);
                }
                else
                    throw (new Exception("指定的客户端没有找到!"));
            }
            catch (Exception e)
            {
                OnErrorServerEvent(new ErrorServerEventArgs(e, new ClientContext(clientkey), TCPErrorType.Unkown));
                LastException = e;
            }
            finally
            {
                try
                {
                    ClientListMutex.ReleaseMutex();
                }
                catch
                {

                }
            }
        }
        ///
        /// 发送一个流数据
        ///
        public void Send(string ip, int port,MemoryStream mStream)
        {
            Send(ip, port,mStream.GetBuffer());
        }
        ///
        /// 发送一个流数据
        ///
        public void Send(string ip, int port, byte[] txBytes)
        {
            ClientContext client = null;
            try
            {
                ClientListMutex.WaitOne();
                foreach (DictionaryEntry de in ClientList)
                {
                    client = (ClientContext)de.Value;
                    if (client.clientEndPoint.Address.ToString() == ip)
                    {
                        if (port != -1)
                        {
                            if(client.clientEndPoint.Port==port)
                                break;
                        }
                        else
                            break;
                    }
                    client = null;
                }               
                if (client != null)
                {
                    Send(client, txBytes);
                }
                else
                    throw (new Exception("指定的客户端没有找到!"));
            }
            catch (Exception e)
            {
                OnErrorServerEvent(new ErrorServerEventArgs(e, null, TCPErrorType.Unkown));
                LastException = e;
            }
            finally
            {
                try
                {
                    ClientListMutex.ReleaseMutex();
                }
                catch
                {

                }
            }
        }
        public void SendToAll(MemoryStream mStream)
        {
            SendToAll(mStream.GetBuffer());
        }
        public void SendToAll(byte[] txBytes)
        {
            ClientContext client = null;
            try
            {
                ClientListMutex.WaitOne();
                foreach (DictionaryEntry c in ClientList)
                {
                    client = (ClientContext)c.Value;
                    Send(client, txBytes);
                }
            }
            catch (Exception e)
            {
                OnErrorServerEvent(new ErrorServerEventArgs(e, null, TCPErrorType.Unkown));
            }
            finally
            {
                try
                {
                    ClientListMutex.ReleaseMutex();
                }
                catch
                {

                }
            }
        }
        public void Send(ClientContext client, MemoryStream mStream)
        {
            Send(client, mStream.GetBuffer());
        }
        public void Send(ClientContext client, byte[] txBytes)
        {
            try
            {
                if (client.ClientSocket.Connected == false)
                {
                    throw (new Exception("没有连接客户端不可以发送信息!"));
                }
                if (txBytes == null || txBytes.Length == 0)
                {
                    throw (new Exception("不可以发送空信息!"));
                }
                OnBeforeSendPacketServerEvent(new BeforeSendPacketEventArgs(client, txBytes));
                //                 TimeSpan t1 = new TimeSpan(mStream.Length * 100);
                //                 TimeSpan t2 = new TimeSpan(-1);
                //                 client.SendOutTimer.Change(t1,t2);                
                client.SendIAsyncResult = client.netStream.BeginWrite(txBytes, 0, (Int32)txBytes.Length, new AsyncCallback(AsyncCallbackWriteToNetStream), new ClientAndPacket(client, txBytes));
            }
            catch (Exception e)
            {
                OnErrorServerEvent(new ErrorServerEventArgs(e, client, TCPErrorType.Unkown));
            }
        }
        /// <summary>
        /// 写入网络流异步回调函数
        /// </summary>
        /// <param name="result"></param>
        private void AsyncCallbackWriteToNetStream(IAsyncResult result)
        {
            try
            {
                ClientAndPacket p = (ClientAndPacket)result.AsyncState;
                p.Client.netStream.EndWrite(result);
                OnSendCompleteServerEvent(new SendCompleteEventArgs(p.Client, p.txBytes));
            }
            catch (IOException e)
            {
                if (e.InnerException.GetType() == typeof(SocketException))
                {
                    SocketException ex = (SocketException)e.InnerException;
                    ClientContext Client = (ClientContext)result.AsyncState;
                    switch (ex.ErrorCode)
                    {
                        case 10054://客户端断开连接
                            ClientListMutex.WaitOne();
                            ClientList.Remove(Client.key);
                            ClientListMutex.ReleaseMutex();
                            OnDisconnectServerEvent(new DisconnectEventArgs((ClientContext)result.AsyncState));
                            break;
                        default:
                            OnErrorServerEvent(new ErrorServerEventArgs(e, TCPErrorType.Unkown));
                            break;
                    }
                }
            }
            catch (SystemException e)
            {
                OnErrorServerEvent(new ErrorServerEventArgs(e, TCPErrorType.Unkown));
            }
        }
        ///
        /// 引发接收事件
        ///
        /// 数据
        protected virtual void OnReceiveServerEvent(ReceiveServerEventArgs e)
        {
            if (ReceiveServerEvent != null)
            {
                ReceiveServerEvent(this, e);
            }
        }
        ///
        /// 引发错误事件
        ///
        /// 数据
        protected virtual void OnErrorServerEvent(ErrorServerEventArgs e)
        {
            if (ErrorServerEvent != null)
            {
                ErrorServerEvent(this, e);
            }
        }
        ///
        /// 引发接入事件
        ///
        /// 数据
        protected virtual void OnAcceptServerEvent(AcceptServerEventArgs e)
        {
            if (AcceptServerEvent != null)
            {
                AcceptServerEvent(this, e);
            }
        }
        ///
        /// 引发发送前事件
        ///
        /// 数据
        protected virtual void OnBeforeSendPacketServerEvent(BeforeSendPacketEventArgs e)
        {
            if (BeforeSendPacketServerEvent != null)
            {
                BeforeSendPacketServerEvent(this, e);
            }
        }
        ///
        /// 引发发送完成事件
        ///
        /// 数据
        protected virtual void OnSendCompleteServerEvent(SendCompleteEventArgs e)
        {
            if (SendCompleteServerEvent != null)
            {
                SendCompleteServerEvent(this, e);
            }
        }
        ///
        /// 引发离线事件
        ///
        /// 数据
        protected virtual void OnDisconnectServerEvent(DisconnectEventArgs e)
        {
            if (DisconnectServerEvent != null)
            {
                DisconnectServerEvent(this, e);
            }
        }
        ///
        /// 接收到数据事件
        ///
        public event TCPReceiveEvent ReceiveServerEvent;
        ///
        /// 发生错误事件
        ///
        public event TCPErrorEvent ErrorServerEvent;
        ///
        /// 发生接入事件
        ///
        public event TCPAcceptEvent AcceptServerEvent;
        ///
        /// 发生发送前事件
        ///
        public event TCPBeforeSendPacketEvent BeforeSendPacketServerEvent;
        ///
        /// 发生发送完成事件
        ///
        public event TCPSendCompleteEvent SendCompleteServerEvent;
        ///
        /// 发生离线事件
        ///
        public event TCPDisconnectEvent DisconnectServerEvent;
    }
}
